package Parse;
import ErrorMsg.ErrorMsg;
%% 

%unicode
%cup
%cupdebug
%line
%column
%char
%state COMMENT,STRING

%{
	StringBuffer str = new StringBuffer();
	
	private static final String errorM[] = {
	  "Error: Unmatched end-of-comment punctuation.",
	  "Error: Unmatched start-of-comment punctuation.",
	  "Error: Unclosed string.",
	  "Error: Illegal character."
	};
	  
	public static final int E_ENDCOMMENT = 0;
	public static final int E_STARTCOMMENT = 1;
	public static final int E_UNCLOSEDSTR = 2;
	public static final int E_ILLEGAL = 3;
	
	
	private void newline() {
	  errorMsg.newline(yychar);
	}
		
	private void err(int pos, String s) {
		errorMsg.error(pos, s);
	}
		
	private void err(String s) {
		err(yychar, s);
	}
		
	private java_cup.runtime.Symbol tok(int kind, Object value) {
		return new java_cup.runtime.Symbol(kind, yychar, yychar+yylength(), value);
	}
		
	/* reload the constructing function so  that we support the ErrorMsg class */
	public Yylex(java.io.FileReader s, ErrorMsg e) {
	  this(s);
	  errorMsg = e;
	}
		
	private ErrorMsg errorMsg;
	private int comment_count = 0;
		
%}
		
%eofval{
	{
	if(zzLexicalState!=0){
		switch(zzLexicalState){
			case 2:		{err(errorM[E_STARTCOMMENT]);
					break;}
			case 4:		{err(errorM[E_UNCLOSEDSTR]);
					break;}
			default:	{ /*do nothing*/ }
		}
	}
	return tok(sym.EOF, null);
	}
%eofval}
	
	/*DEFINITIONS OF TERMINAL KEY WORDS*/
	ALPHA=[A-Za-z]
	DIGIT=[0-9]
	LINE_TERMINATOR = \r|\n|\r\n
	NONNEWLINE_WHITE_SPACE_CHAR=[\ \t\f\b\012]
	WHITE_SPACE_CHAR = {LINE_TERMINATOR} | {NONNEWLINE_WHITE_SPACE_CHAR}

%%

/* TOKENS : KEYWORDS */
<YYINITIAL> "SELECT"		{ return tok(sym.SELECT,null); }
<YYINITIAL> "FROM"		{ return tok(sym.FROM,null); }
<YYINITIAL> "AS"		{ return tok(sym.AS,null); }
<YYINITIAL> "WHERE"		{ return tok(sym.WHERE,null); }
<YYINITIAL> "DISTINCT" 	 	{ return tok(sym.DISTINCT,null); }
<YYINITIAL> "TOP"		{ return tok(sym.TOP,null); }
<YYINITIAL> "PERCENT"		{ return tok(sym.PERCENT,null); }
<YYINITIAL> "NOT" 		{ return tok(sym.NOT,null); }
<YYINITIAL> "AND" 		{ return tok(sym.AND,null); }
<YYINITIAL> "OR"		{ return tok(sym.OR,null); }
<YYINITIAL> "BETWEEN"		{ return tok(sym.BETWEEN,null); }
<YYINITIAL> "EXISTS"		{ return tok(sym.EXISTS,null); }
<YYINITIAL> "IN"		{ return tok(sym.IN,null); }
<YYINITIAL> "ORDER" 		{ return tok(sym.ORDER,null); }
<YYINITIAL> "BY"		{ return tok(sym.BY,null); }
<YYINITIAL> "DESC" 		{ return tok(sym.DESC,null); }
<YYINITIAL> "ASC"		{ return tok(sym.ASC,null); }
<YYINITIAL> "UNION" 		{ return tok(sym.UNION,null); }
<YYINITIAL> "INNER" 		{ return tok(sym.INNER,null); }
<YYINITIAL> "CROSS" 		{ return tok(sym.CROSS,null); }
<YYINITIAL> "LEFT" 		{ return tok(sym.LEFT,null); }
<YYINITIAL> "RIGHT" 		{ return tok(sym.RIGHT,null); }
<YYINITIAL> "FULL"		{ return tok(sym.FULL,null); }
<YYINITIAL> "OUTER" 		{ return tok(sym.OUTER,null); }
<YYINITIAL> "JOIN" 		{ return tok(sym.JOIN,null); }
<YYINITIAL> "ON" 		{ return tok(sym.ON,null); }
<YYINITIAL> "COUNT" 		{ return tok(sym.COUNT,null); }
<YYINITIAL> "SUM" 		{ return tok(sym.SUM,null); }
<YYINITIAL> "AVG" 		{ return tok(sym.AVG,null); }
<YYINITIAL> "CREATE" 		{ return tok(sym.CREATE,null); }
<YYINITIAL> "DROP" 		{ return tok(sym.DROP,null); }
<YYINITIAL> "ALTER" 		{ return tok(sym.ALTER,null); }
<YYINITIAL> "ADD" 		{ return tok(sym.ADD,null); }
<YYINITIAL> "COLUMN" 		{ return tok(sym.COLUMN,null); }
<YYINITIAL> "DELETE" 		{ return tok(sym.DELETE,null); }
<YYINITIAL> "UPDATE" 		{ return tok(sym.UPDATE,null); }
<YYINITIAL> "SET" 		{ return tok(sym.SET,null); }
<YYINITIAL> "TABLE" 		{ return tok(sym.TABLE,null); }
<YYINITIAL> "PRIMARY" 		{ return tok(sym.PRIMARY,null); }
<YYINITIAL> "KEY" 		{ return tok(sym.KEY,null); }
<YYINITIAL> "INSERT" 		{ return tok(sym.INSERT,null); }
<YYINITIAL> "INTO" 		{ return tok(sym.INTO,null); }
<YYINITIAL> "VALUES" 		{ return tok(sym.VALUES,null); }
<YYINITIAL> "HAVING" 		{ return tok(sym.HAVING,null); }
<YYINITIAL> "CHAR" 		{ return tok(sym.CHAR,null); }
<YYINITIAL> "DATE" 		{ return tok(sym.DATE,null); }
<YYINITIAL> "MONEY" 		{ return tok(sym.MONEY,null); }
<YYINITIAL> "VARCHAR" 		{ return tok(sym.VARCHAR,null); }

/* TOKENS : SEPARATORS AND OPERATORS */

<YYINITIAL> ","  { return tok(sym.COMMA,null); }
<YYINITIAL> "("  { return tok(sym.LPAREN,null); }
<YYINITIAL> ")"  { return tok(sym.RPAREN,null); }
<YYINITIAL> "["  { return tok(sym.LBRACK,null); }
<YYINITIAL> "]"  { return tok(sym.RBRACK,null); }
<YYINITIAL> "."  { return tok(sym.DOT,null); }
<YYINITIAL> "*"  { return tok(sym.TIMES,null); }
<YYINITIAL> "/"  { return tok(sym.DIVIDE,null); }
<YYINITIAL> "="  { return tok(sym.EQ,null); }
<YYINITIAL> "<>" { return tok(sym.NEQ,null); }
<YYINITIAL> "<"  { return tok(sym.LT,null); }
<YYINITIAL> "<=" { return tok(sym.LE,null); }
<YYINITIAL> ">"  { return tok(sym.GT,null); }
<YYINITIAL> ">=" { return tok(sym.GE,null); }
<YYINITIAL> "|" { return tok(sym.PIPE,null); }


<YYINITIAL> {NONNEWLINE_WHITE_SPACE_CHAR}+ { }       /*Do nothing*/

<YYINITIAL,COMMENT,STRING> {LINE_TERMINATOR} { newline(); }

<YYINITIAL> "/*" { yybegin(COMMENT); comment_count = comment_count + 1; }

<YYINITIAL> "*/" { err(errorM[E_ENDCOMMENT]); }

/*STATE OF COMMENT*/
<COMMENT> "/*" { comment_count = comment_count + 1; }

<COMMENT> "*/" { 
	comment_count = comment_count - 1; 
	if (comment_count == 0) {
		yybegin(YYINITIAL);
	}
}

<COMMENT> . { /*do nothing*/ }

<YYINITIAL> \" {  str.setLength(0); yybegin(STRING);}

<STRING> [^\n\r\"\\]+ { str.append(yytext()); }
<STRING> \\n { str.append('\n'); }
<STRING> \\t { str.append('\t'); }
<STRING> \\\" { str.append('\"'); }
<STRING> \\\\ { str.append('\\'); }
<STRING> \\{WHITE_SPACE_CHAR}+\\ { }


<STRING> \\\^[@A-Z_\[\\\]\^_] {
	str.append((char)((int)(yytext().charAt(2))-64));
}
	
<STRING> \\0{DIGIT}{DIGIT}|\\1[0-1]{DIGIT}|\\12[0-7] {
	str.append((char)Integer.valueOf(new String(yytext().getBytes(),1,3)).intValue());
}

<STRING> \" {
	yybegin(YYINITIAL);
	return tok(sym.STRING,str.toString());
}

<STRING> . {
	err(errorM[E_ILLEGAL]);
}

<YYINITIAL> {DIGIT}+ {
	return tok(sym.INT,yytext());
}

<YYINITIAL> {ALPHA}({ALPHA}|{DIGIT}|_)* {
	return tok(sym.ID,yytext());
}	

<YYINITIAL> . {
	err(errorM[E_ILLEGAL]);
}

